package de.velvettear.squirrel.gui;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.ActionBar.TabListener;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.FragmentTransaction;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnCreateContextMenuListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.ExpandableListView;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.Spinner;
import android.widget.Toast;
import de.velvettear.squirrel.R;
import de.velvettear.squirrel.adapter.NFCTagAdapter;
import de.velvettear.squirrel.kernel.NFCTag;
import de.velvettear.squirrel.kernel.Statics;
import de.velvettear.squirrel.util.ApplicationHelper;
import de.velvettear.squirrel.util.NotificationHelper;

public class NFCFrame extends FragmentActivity {
				
	private static Activity activity;	
	
	private static ViewPager viewPager;
	private static SectionsPagerAdapter sectionsPagerAdapter;	
	private static ActionBar actionBar;
			
	private static final String SAVESTATE_CREATING = "SAVESTATE_CREATING";
	private static final String SAVESTATE_EDITING = "SAVESTATE_EDITING";
	private static final String SAVESTATE_ID = "SAVESTATE_ID";
	private static final String SAVESTATE_NAME = "SAVESTATE_NAME";
	private static final String SAVESTATE_TYPE = "SAVESTATE_TYPE";
	private static final String SAVESTATE_APP = "SAVESTATE_APP";
	private static final String SAVESTATE_URL = "SAVESTATE_URL";
	private static final String SAVESTATE_EXTRAS = "SAVESTATE_EXTRAS";
	
	private static boolean isEditing = false;
	private static boolean isCreating = false;
	private static String id = "";
	private static String name = "";
	private static String type = Statics.NFC_TYPE_APP;
	private static int app = -1;
	private static String url = "";
	private static Vector<String> extras = new Vector<String>();
		
	private static List<String> appNames;
	
	// NFCTagListFragment
	private static NFCTagAdapter adapter = null;	
	private static ExpandableListView lv_tags;
	
	// NFCTagEditorFragment
	private static EditText et_id;
	private static EditText et_name;
	private static LinearLayout ll_app;
	private static LinearLayout ll_url;
	private static Spinner sp_app;
	private static EditText et_url;
	private static RadioButton rb_app;
	private static RadioButton rb_url;
	private static CheckBox cb_wlan;
	private static CheckBox cb_bluetooth;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_nfcframe);
				
		activity = this;
		
		actionBar = getActionBar();
		actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
		
		sectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

		viewPager = (ViewPager) findViewById(R.id.pager);
		viewPager.setAdapter(sectionsPagerAdapter);

		viewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
			@Override
			public void onPageSelected(int position) {
				actionBar.setSelectedNavigationItem(position);
			}
		});
		
		if (savedInstanceState != null) {
			isCreating = savedInstanceState.getBoolean(SAVESTATE_EDITING);
			isEditing = savedInstanceState.getBoolean(SAVESTATE_EDITING);
			id = savedInstanceState.getString(SAVESTATE_ID);
			name = savedInstanceState.getString(SAVESTATE_NAME);
			type = savedInstanceState.getString(SAVESTATE_TYPE);
			app = savedInstanceState.getInt(SAVESTATE_APP);
			url = savedInstanceState.getString(SAVESTATE_URL);
		}
		
		NotificationHelper.setNotification(this, Statics.NOTIFICATION_ID_NFC);	
		
		setTabs();
	}
			
	@Override
	public void onResume() {
		super.onResume();	
		
		activity = this;
	}
	
	@Override
	public void onDestroy() {
		super.onDestroy();
		
		setDefaultValues();
	}
	
	@Override
	public void onSaveInstanceState(Bundle savedInstanceState) {
	   super.onSaveInstanceState(savedInstanceState);
	   savedInstanceState.putBoolean(SAVESTATE_CREATING, isCreating);
	   savedInstanceState.putBoolean(SAVESTATE_EDITING, isEditing);
	   if (et_id != null) {
		   savedInstanceState.putString(SAVESTATE_ID, et_id.getText().toString());
	   }
	   if (et_name != null) {
		   savedInstanceState.putString(SAVESTATE_NAME, et_name.getText().toString());
	   }
	   savedInstanceState.putString(SAVESTATE_TYPE, type);
	   if (et_url != null) {
		   savedInstanceState.putString(SAVESTATE_URL, et_url.getText().toString());
	   }
	   if (sp_app != null) {
		   savedInstanceState.putInt(SAVESTATE_APP, sp_app.getSelectedItemPosition());
	   }
	}
	
	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent intent) {
		super.onActivityResult(requestCode, resultCode, intent);	
				
		if (requestCode == Statics.REQUEST_NFC) {
			if (resultCode == RESULT_OK) {
				if (intent.hasExtra(Statics.NFC_RETURN_MODE)) {
					String tagID = intent.getExtras().getString(Statics.NFC_RETURN_MODE);
					NFCTag nfcTag = new NFCTag();
					nfcTag.getTagByTagID(tagID);
					if (nfcTag.isValid()) {
						Toast.makeText(this, "NFC-Tag already in use (" + nfcTag.m_sName + ")!", Toast.LENGTH_SHORT).show();
					} else {
						fillEditorFragment(tagID, true, false);
					}
				}				
			}
		}		
	}
		
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {		
		getMenuInflater().inflate(R.menu.menu_nfctagsframe, menu);	
				
		if (getCurrentFragment() == Statics.ID_NFCFRAGMENT_TAGLIST) {
			menu.removeItem(R.id.menu_nfctagsframe_accept);
			menu.removeItem(R.id.menu_nfctagsframe_cancel);
		} else if (getCurrentFragment() == Statics.ID_NFCFRAGMENT_TAGEDITOR) {
			menu.removeItem(R.id.menu_nfctagsframe_add);
		}
		
		return super.onCreateOptionsMenu(menu);	
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch(item.getItemId()) {
				
		case R.id.menu_nfctagsframe_add:
			if (isEditing) {
				Toast.makeText(this, "Already editing a tag!", Toast.LENGTH_SHORT).show();
			} else if (isCreating) {
				Toast.makeText(this, "Already creating a tag!", Toast.LENGTH_SHORT).show();
			} else {
				Intent scanIntent = new Intent(this, ScanFrame.class);
				scanIntent.putExtra(Statics.NFC_RETURN_MODE, true);
				startActivityForResult(scanIntent, Statics.REQUEST_NFC);
			}			
			break;
			
		case R.id.menu_nfctagsframe_accept:
			save();
			break;
			
		case R.id.menu_nfctagsframe_cancel:
			clearEditorFragment();
			break;
			
		} 
		return super.onOptionsItemSelected(item);
	}
	
	@Override
	public void onBackPressed() {
		if (isCreating || isEditing) {
			AlertDialog exitDialog = new AlertDialog.Builder(this).create();
			exitDialog.setTitle("Exit");
			exitDialog.setMessage("Do you really want to exit without saving?");
			exitDialog.setButton(AlertDialog.BUTTON_POSITIVE, "Yes", new DialogInterface.OnClickListener() {			
				@Override
				public void onClick(DialogInterface dialog, int which) {
					Intent mainIntent = new Intent(NFCFrame.this, MainFrame.class);
					startActivity(mainIntent);
					finish();
				}
			});
			exitDialog.setButton(AlertDialog.BUTTON_NEGATIVE, "No", new DialogInterface.OnClickListener() {			
				@Override
				public void onClick(DialogInterface dialog, int which) {
					
				}
			});
			exitDialog.show();			
		} else {
			finish();
			Intent mainIntent = new Intent(NFCFrame.this, MainFrame.class);
			startActivity(mainIntent);
		}		
	}
			
	private static void setDefaultValues() {
		isEditing = false;
		isCreating = false;
		id = "";
		name = "";
		type = Statics.NFC_TYPE_APP;
		app = -1;
		url = "";
		extras = new Vector<String>();
	}
	
	private static void clearEditorFragment() {
		setDefaultValues();
		setTabs();
		viewPager.setCurrentItem(0, true);
	}
	
	public static void fillEditorFragment(String tagID, boolean creating, boolean editing) {	
		NFCTag tag = new NFCTag();
		tag.getTagByTagID(tagID);
		if (!tag.isValid()) {
			tag = new NFCTag();
			tag.m_sTagID = tagID;
		}
		fillEditorFragment(tag, creating, editing);
	}
	
	public static void fillEditorFragment(NFCTag tag, boolean creating, boolean editing) {					
		if (creating) {
			isCreating = creating;
			isEditing = editing;
			
			setTabs();	
			
			et_id.setText(tag.m_sTagID);
			
			viewPager.setCurrentItem(1);
		} else if (editing) {
			if (tag.isValid()) {		
				isCreating = creating;
				isEditing = editing;
				
				setTabs();	
				
				et_id.setText(tag.m_sTagID);
				et_name.setText(tag.m_sName);
				
				if (tag.m_sType.equals(Statics.NFC_TYPE_APP)) {
					rb_app.setChecked(true);
					for (int pos = 0; pos < sp_app.getAdapter().getCount(); pos++) {
						if (sp_app.getAdapter().getItem(pos).equals(tag.m_sAction)) {
							sp_app.setSelection(pos);
						}
					}
				} else if (tag.m_sType.equals(Statics.NFC_TYPE_URL)) {
					rb_url.setChecked(true);
					et_url.setText(tag.m_sAction);
				}
							
				viewPager.setCurrentItem(1);
			}	
		}		
	}
		
	public static void setTabs() {
		actionBar.removeAllTabs();
		sectionsPagerAdapter.notifyDataSetChanged();
		for (int i = 0; i < sectionsPagerAdapter.getCount(); i++) {
			actionBar.addTab(actionBar.newTab().setText(sectionsPagerAdapter.getPageTitle(i)).setTabListener(new TabListener() {
				
				@Override
				public void onTabUnselected(Tab tab, FragmentTransaction ft) {					
					
				}
				
				@Override
				public void onTabSelected(Tab tab, FragmentTransaction ft) {
					viewPager.setCurrentItem(tab.getPosition());	
					activity.invalidateOptionsMenu();
				}
				
				@Override
				public void onTabReselected(Tab tab, FragmentTransaction ft) {	
					
				}
			}));
		}
		sectionsPagerAdapter.notifyDataSetChanged();
	}
	
	private static void save() {
		Vector<String> missingFields = requiredFieldsSet();
		if (missingFields.isEmpty()) {
			boolean addToAdapter = false;
			NFCTag tag = new NFCTag();
			tag.getTagByTagID(et_id.getText().toString());
			if (!tag.isValid()) {
				tag = new NFCTag();
				addToAdapter = true;
			}
			
			tag.m_sTagID = et_id.getText().toString();
			tag.m_sName = et_name.getText().toString();
			tag.m_sType = type;
			if (type.equals(Statics.NFC_TYPE_APP)) {
				tag.m_sAction = sp_app.getSelectedItem().toString();
			} else if (type.equals(Statics.NFC_TYPE_URL)) {
				tag.m_sAction = et_url.getText().toString();
			}
			
			for (String extra : extras) {
				tag.addExtra(extra);
			}
			tag.store();
			
			clearEditorFragment();
			
			if (addToAdapter) {
				adapter.addItem(tag);
			}
		} else {
			String fields = "";
			for (String field : missingFields) {
				fields += field + ", ";
			}
			fields = fields.substring(0, fields.lastIndexOf(","));
			
			Toast.makeText(activity, "Required fields are missing: " + fields, Toast.LENGTH_SHORT).show();
		}
	}
	
	private static Vector<String> requiredFieldsSet() {
		Vector<String> missingFields = new Vector<String>();
		if (et_name.getText().toString().trim().length() == 0) {
			missingFields.add("Name");
		}		
		if (type.equals(Statics.NFC_TYPE_APP)) {
			if (sp_app.getSelectedItem() == null) {
				missingFields.add("App");
			}
		} else if (type.equals(Statics.NFC_TYPE_URL)) {
			if (et_url.getText().toString().trim().length() == 0) {
				missingFields.add("URL");
			}
		}
		return missingFields;
	}
	
	private static int getCurrentFragment() {
		return (int) sectionsPagerAdapter.getItemId(viewPager.getCurrentItem());
	}
		
	public class SectionsPagerAdapter extends FragmentPagerAdapter {

		public SectionsPagerAdapter(FragmentManager fm) {
			super(fm);
		}

		@Override
		public Fragment getItem(int position) {
			switch (position) {
			
			case 0: return NFCTagListFragment.newInstance();
			
			case 1: return NFCTagEditorFragment.newInstance();
			
			default: return NFCTagListFragment.newInstance();
			
			}
		}

		@Override
		public int getCount() {	
			if (isEditing || isCreating) {
				return 2;
			} else {
				return 1;
			}			
		}

		@Override
		public CharSequence getPageTitle(int position) {
			switch (position) {
			case 0:
				return Statics.NFC_TAGS;
				
			case 1:
				return Statics.TAG_EDITOR;
			}
			return null;
		}
	}
		
	public static class NFCTagListFragment extends Fragment implements OnCreateContextMenuListener {
				
		private final static int CONTEXTMENU_EDIT = 0;
		private final static int CONTEXTMENU_DELETE = 1;
					
		private NFCTag selectedTag = null;
		private int selectedPosition = -1;
		
		public NFCTagListFragment() {
		
		}

		public static NFCTagListFragment newInstance() {
			NFCTagListFragment fragment = new NFCTagListFragment();
			return fragment;
		}
		
		@Override
		public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
			View rootView = inflater.inflate(R.layout.fragment_nfctags, container, false);
					
			init(rootView);
			
			return rootView;
		}

		@Override
		public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
			super.onCreateContextMenu(menu, v, menuInfo);						
			ExpandableListView.ExpandableListContextMenuInfo info = (ExpandableListView.ExpandableListContextMenuInfo) menuInfo;
						
			selectedPosition = ExpandableListView.getPackedPositionGroup(info.packedPosition);
			selectedTag = (NFCTag) adapter.getGroup(selectedPosition);
						
			menu.setHeaderTitle(selectedTag.m_sName);
			if (selectedTag.m_sType.equals(Statics.NFC_TYPE_URL)) {
				menu.setHeaderIcon(R.drawable.icon_web);
			} else if (selectedTag.m_sType.equals(Statics.NFC_TYPE_APP)) {
				menu.setHeaderIcon(R.drawable.icon_externalapp);
			}
			menu.add(Menu.NONE, CONTEXTMENU_EDIT, CONTEXTMENU_EDIT, "Edit ...");		
			menu.add(Menu.NONE, CONTEXTMENU_DELETE, CONTEXTMENU_DELETE, "Delete ...");				
		}
		
		@Override
		public boolean onContextItemSelected(MenuItem menuItem) {
			ContextMenuInfo info = (ContextMenuInfo) menuItem.getMenuInfo();		
									
			switch (menuItem.getItemId()) {
							
			case CONTEXTMENU_EDIT:
				if (selectedTag != null && selectedPosition > -1) {
					fillEditorFragment(selectedTag, false, true);
				} else {
					Toast.makeText(getActivity(), "Error editing \"" + selectedTag.m_sName + "\" !", Toast.LENGTH_SHORT).show();	
				}	
				break;
				
			case CONTEXTMENU_DELETE:
				if (selectedTag != null && selectedPosition > -1) {
					selectedTag.delete();
					adapter.removeItem(selectedPosition);
					selectedPosition = -1;
					Toast.makeText(getActivity(), "\"" + selectedTag.m_sName + "\" successfully deleted!", Toast.LENGTH_SHORT).show();	
				} else {
					Toast.makeText(getActivity(), "Error deleting \"" + selectedTag.m_sName + "\" !", Toast.LENGTH_SHORT).show();	
				}	
				break;
			
			}
			
			return false;
			
		}
		
		private void init(View rootView) {
			lv_tags = (ExpandableListView) rootView.findViewById(R.id.nfctags_lv);	
						
			Vector<NFCTag> tags = new NFCTag().select(null, "m_sName", false);
					
			if (adapter == null) {
				adapter = new NFCTagAdapter(getActivity(), tags);
			}
			
			lv_tags.setAdapter(adapter);
			lv_tags.setOnCreateContextMenuListener(this);
		}
					
	}	
	
	public static class NFCTagEditorFragment extends Fragment implements OnCheckedChangeListener {
				
		private ArrayAdapter adapter;
		
		public NFCTagEditorFragment() {
		
		}

		public static NFCTagEditorFragment newInstance() {
			NFCTagEditorFragment fragment = new NFCTagEditorFragment();
			return fragment;
		}
		
		@Override
		public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
			View rootView = inflater.inflate(R.layout.fragment_nfctageditor, container, false);
					
			init(rootView);
			
			return rootView;
		}
		
		private void init(View rootView) {
			et_id = (EditText) rootView.findViewById(R.id.nfctageditor_et_id);
			et_name = (EditText) rootView.findViewById(R.id.nfctageditor_et_name);			
			ll_app = (LinearLayout) rootView.findViewById(R.id.nfctageditor_ll_app);
			ll_url = (LinearLayout) rootView.findViewById(R.id.nfctageditor_ll_url);
			sp_app = (Spinner) rootView.findViewById(R.id.nfctageditor_sp_app);
			et_url = (EditText) rootView.findViewById(R.id.nfctageditor_et_url);
			rb_app = (RadioButton) rootView.findViewById(R.id.nfctageditor_rb_app);
			rb_url = (RadioButton) rootView.findViewById(R.id.nfctageditor_rb_url);
			cb_wlan = (CheckBox) rootView.findViewById(R.id.nfctageditor_cb_wlan);
			cb_bluetooth = (CheckBox) rootView.findViewById(R.id.nfctageditor_cb_bluetooth);
						
			if (type.equals(Statics.NFC_TYPE_APP)) {
				rb_app.setChecked(true);
				rb_url.setChecked(false);
			} else if (type.equals(Statics.NFC_TYPE_URL)) {
				rb_app.setChecked(false);
				rb_url.setChecked(true);
			}
			
			checkMode();
			
			appNames = new ArrayList<String>();
			for (ResolveInfo info : ApplicationHelper.getApplicationList(getActivity())) {
				appNames.add(info.activityInfo.packageName);
			}
			
			adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_spinner_dropdown_item, appNames);
			sp_app.setAdapter(adapter);
			
			et_id.setText(id);
			et_name.setText(name);
			sp_app.setSelection(app, true);
			et_url.setText(url);
			
			if (extras.contains(Statics.NFC_EXTRA_WLAN)) {
				cb_wlan.setChecked(true);
			} else {
				cb_wlan.setChecked(false);
			}
			if (extras.contains(Statics.NFC_EXTRA_BLUETOOTH)) {
				cb_bluetooth.setChecked(true);
			} else {
				cb_bluetooth.setChecked(false);
			}
			
			cb_wlan.setOnCheckedChangeListener(this);
			cb_bluetooth.setOnCheckedChangeListener(this);
			
			rb_app.setOnCheckedChangeListener(this);
			rb_url.setOnCheckedChangeListener(this);
		}

		private void checkMode() {
			if (type.equals(Statics.NFC_TYPE_APP)) {
				ll_app.setVisibility(View.VISIBLE);
				ll_url.setVisibility(View.GONE);
			} else if (type.equals(Statics.NFC_TYPE_URL)) {
				ll_url.setVisibility(View.VISIBLE);
				ll_app.setVisibility(View.GONE);
			}
		}
		
		@Override
		public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
			switch(buttonView.getId()) {
			
			case R.id.nfctageditor_cb_wlan:
				if (isChecked) {
					extras.add(Statics.NFC_EXTRA_WLAN);
				} else {
					extras.remove(Statics.NFC_EXTRA_WLAN);
				}
				break;
				
			case R.id.nfctageditor_cb_bluetooth:
				if (isChecked) {
					extras.add(Statics.NFC_EXTRA_BLUETOOTH);
				} else {
					extras.remove(Statics.NFC_EXTRA_BLUETOOTH);
				}
				break;
			
			case R.id.nfctageditor_rb_app:
				if (isChecked) {
					type = Statics.NFC_TYPE_APP;
					checkMode();
				}
				break;
				
			case R.id.nfctageditor_rb_url:
				if (isChecked) {
					type = Statics.NFC_TYPE_URL;
					checkMode();
				}
				break;
			
			}
			
		}
					
	}	
	
}
